function ScrollAnimation() {
    // this.Manager = new __ScrollAnimationManager();
    if ($(window).data('ScrollAnimation'))
        this.Manager = $(window).data('ScrollAnimation');
    else {
        this.Manager = new __ScrollAnimationManager();
        $(window).data('ScrollAnimation', this.Manager);
        $(window).scroll(function (s) {
            $(this).data('ScrollAnimation').OnScroll($(this).scrollTop());
        });
        $(window).load(function () {
            $(this).data('ScrollAnimation').Update();
        });
    }
};

/*Dodaje nowy ramkę.
options: (Obiekt typu ScrollAnimationFrame
Frame - określa wartość scrollTop
OnHitDown - funkcja wywołana po osiągnięciu scrolla, przy scroll down - jako argument dostaje options
OnHitUp - funkcja wywołana po osiągnięciu scrolla, przy scroll up - jako argument dostaje options
*/
ScrollAnimation.prototype.AddFrame = function (options) {
    this.Manager.AddFrame(options);
};

function __ScrollAnimationManager() {
    this.UpBreak = -1;
    this.DownBreak = 100000;
    this.CurrentBreak = -1;
    this.CurrentScroll = $(window).scrollTop();
    if (!this.CurrentScroll) this.CurrentScroll = 0;
    this.Frames = new Array();
    this.FramesIndexing = new Array();
};

__ScrollAnimationManager.prototype.AddFrame = function (options) {
    this.Frames[options.Frame] = options;
    if (options.Frame > this.UpBreak && options.Frame < this.CurrentBreak)
        this.UpBreak = options.Frame;
    if (options.Frame > this.CurrentBreak && options.Frame < this.DownBreak)
        this.DownBreak = options.Frame;
    this.FramesIndexing.push(options.Frame);
    this.FramesIndexing.sort();
};
__ScrollAnimationManager.prototype.Update = function () {
    var actualScrollTop = $(window).scrollTop();
    if (actualScrollTop > 0) {
        this.CurrentScroll = this.CurrentBreak - 1; // WYmusza właściwy kierunek pseudoanimacji scrolla
        for (var xf = 0; xf < this.FramesIndexing.length; xf++) {
            if (this.FramesIndexing[xf] > this.CurrentBreak && this.FramesIndexing[xf] <= actualScrollTop)
                this.OnScroll(this.FramesIndexing[xf]);
            else
                break;
        }
    }
};
__ScrollAnimationManager.prototype.OnScroll = function (scrollTop) {
    var direction = 'down';
    if (scrollTop < this.CurrentScroll) direction = 'up';
    this.CurrentScroll = scrollTop;
    if (direction == 'down' && scrollTop >= this.DownBreak) { // mamy przekroczenie scroll'a
        this.__ResetUpAndDownBreaks(this.DownBreak, direction);
        var crnFrame = this.Frames[this.CurrentBreak];
        if (crnFrame.OnHitDown)
            crnFrame.OnHitDown(crnFrame);
    } else if (direction == 'up' && scrollTop <= this.UpBreak) {
        this.__ResetUpAndDownBreaks(this.UpBreak, direction);
        var crnFrame = this.Frames[this.CurrentBreak];
        if (crnFrame.OnHitUp)
            crnFrame.OnHitUp(crnFrame);
    }
};
__ScrollAnimationManager.prototype.__ResetUpAndDownBreaks = function (currentBreak, direction) {
    this.CurrentBreak = currentBreak;
    var crnBreakIdx = this.FramesIndexing.indexOf(currentBreak);
    if (direction == 'down') {
        this.UpBreak = this.CurrentBreak;
        if (crnBreakIdx < this.FramesIndexing.length - 1)
            this.DownBreak = this.FramesIndexing[crnBreakIdx + 1];
        else
            this.DownBreak = 10000;
    } else {
        if (crnBreakIdx > 0)
            this.UpBreak = this.FramesIndexing[crnBreakIdx - 1];
        else
            this.UpBreak = -1;
        this.DownBreak = this.CurrentBreak;
    }
};
function ScrollAnimationFrame() {
    this.Frame = 0;
    this.OnHitDown = function () { };
    this.OnHitUp = function () { };
};
